//============================================================================
// Copyright (C) 2003-2013 Brett R. Jones 
//
// Issued to public domain 2013
//
// brettjones1900@gmail.com
// http://www.p2panarchy.com
//============================================================================

#include "VxNetLib.h"
#include <VxUtilLib/VxParse.h>
#include <VxUtilLib/VxGlobals.h>
#include <VxUtilLib/VxConnectId.h>
#include "VxSktCrypto.h"
#include "VxSktBase.h"


//=================================================================
// Key generation methods
//=================================================================
static unsigned char g_au8RandomData[ 256 ] =
{
#include "VxSktRandomData.h"
};
//---------------------------------------------------------------------------
unsigned char * GetVxSktRandData( int iRandDataIdx )
{
	return &g_au8RandomData[ iRandDataIdx ];
}
//---------------------------------------------------------------------------
//! generate connection key from network identity
RCODE GenerateConnectionKey(	VxKey *					poRetKey,	// set this key
								VxConnectId *			poConnectId )	// network identity
{
	std::string csNetName	= VxGetRogueNetworkName(); //network name

	U64 u64IdLowPart = poConnectId->m_u64IdLoPart;
	vx_assert( u64IdLowPart );
	U64 u64IdHiPart	= poConnectId->m_u64IdHiPart;
	vx_assert( u64IdHiPart );
	std::string strIPv4;
	poConnectId->getIPv4(strIPv4);
	//std::string strIPv6;
	//poConnectId->getIPv6(strIPv6);
//	VxInetAddress oIp		= poConnectId->m_oOnlineIp;
//	vx_assert( oIp.isValid() );
	U16 u16Port		= poConnectId->m_u16OnlinePort;
	vx_assert( u16Port );

	//log_msg( LOG_INFO, "GenerateConnectionKey: creating pwd\n");
	std::string strPwd;
	StdStringFormat( strPwd, "%s%s%d%llx%llx", 
				csNetName.c_str(), 
				strIPv4.c_str(), 
				u16Port, 
				u64IdLowPart, 
				u64IdHiPart );
	if( 64 < strPwd.size() )
	{
		strPwd = strPwd + "rio432#$$&LBHKdgasxvml;";
	}
	//log_msg( LOG_INFO, "GenerateConnectionKey: setting pwd Key size %d addr 0x%x\n", sizeof( VxKey ), poRetKey);
	poRetKey->SetKeyFromPassword( strPwd.c_str(), (int)strPwd.size() );

	//log_msg( LOG_INFO, "GenerateConnectionKey: mixing it up\n");

	// mix it up a bit just for fun
	U32 * pu32Temp = poRetKey->m_au32Key;
	U32 u32PortAndId = u16Port * 892347665;
	u32PortAndId += (U32)(u64IdLowPart * 415788975);
	//log_msg( LOG_INFO, "GenerateConnectionKey: mixing it up part1 m_au32Key 0x%x pu32Temp 0x%x\n",  
	//	poRetKey->m_au32Key, pu32Temp );
	for( int i = 1; i < 4; i++ )
	{
		pu32Temp[ i ] += u32PortAndId;
	}
	//log_msg( LOG_INFO, "GenerateConnectionKey: mixing it up part2\n");

	U32 u32Temp2 = pu32Temp[2];
	//log_msg( LOG_INFO, "GenerateConnectionKey: mixing it up part3 pu32Temp 0x%x\n", pu32Temp);

	for(  int i = 0; i < 4; i++ )
	{
		pu32Temp[ i ] += u32Temp2;
	}
	//log_msg( LOG_INFO, "GenerateConnectionKey: done\n");

	return 0;
}
//---------------------------------------------------------------------------
//! generate key from net identity and connection data and place int sockets m_oRxKey and initialize its crypto
RCODE GenerateRxConnectionKey(	VxSktBase *			poSkt,			// pointer to VxSktBase
								VxConnectId *		poConnectId )		// network identity
{
	RCODE rc = GenerateConnectionKey(	&poSkt->m_oRxKey,		// set this key
										poConnectId );				// announcement packet	
	if( 0 == rc )
	{
		poSkt->m_oRxCrypto.ImportKey( &poSkt->m_oRxKey );
	}
	else
	{
		vx_assert( false );
	}
	return rc;
}

//---------------------------------------------------------------------------
//! generate key from net identity and connection data and place int sockets m_oTxKey and initialize its crypto
RCODE GenerateTxConnectionKey(	VxSktBase *			poSkt,			// pointer to VxSktBase
								VxConnectId *		poConnectId )		// announce packet
{
	RCODE rc = GenerateConnectionKey(	&poSkt->m_oTxKey,	// set this key
										poConnectId );			// announcement packet	
	if( 0 == rc )
	{
		poSkt->m_oTxCrypto.ImportKey( &poSkt->m_oTxKey );
	}
	else
	{
		vx_assert( false );
	}
	return rc;
}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//! generate key from net identity and connection data and place int sockets m_oRxKey and initialize its crypto
RCODE GenerateRxConnectionKey(	VxSktConnectSimple *	poSkt,			// pointer to VxSktConnectSimple
								VxConnectId *		poConnectId )		// network identity
{
	RCODE rc = GenerateConnectionKey(	&poSkt->m_oRxKey,		// set this key
		poConnectId );				// announcement packet	
	if( 0 == rc )
	{
		poSkt->m_oRxCrypto.ImportKey( &poSkt->m_oRxKey );
	}
	else
	{
		vx_assert( false );
	}
	return rc;
}

//---------------------------------------------------------------------------
//! generate key from net identity and connection data and place int sockets m_oTxKey and initialize its crypto
RCODE GenerateTxConnectionKey(	VxSktConnectSimple *		poSkt,			// pointer to VxSktConnectSimple
								VxConnectId *			poConnectId )		// announce packet
{
	RCODE rc = GenerateConnectionKey(	&poSkt->m_oTxKey,	// set this key
		poConnectId );			// announcement packet	
	if( 0 == rc )
	{
		poSkt->m_oTxCrypto.ImportKey( &poSkt->m_oTxKey );
	}
	else
	{
		vx_assert( false );
	}
	return rc;
}
